package com.github.zzay.user.controller;

import com.github.zzay.common.core.model.ResponseBean;
import com.github.zzay.common.core.annotation.MyRateLimit;
import com.github.zzay.user.dto.UserDto;
import com.github.zzay.user.service.UserService;
import com.netflix.hystrix.contrib.javanica.annotation.DefaultProperties;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixCommand;
import com.netflix.hystrix.contrib.javanica.annotation.HystrixProperty;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.responses.ApiResponse;
import io.swagger.v3.oas.annotations.responses.ApiResponses;
import io.swagger.v3.oas.annotations.security.SecurityRequirement;
import io.swagger.v3.oas.annotations.tags.Tag;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.Map;

/**
 * @author zzay
 * @className UserController
 * @description User Controller
 * @create 2022/04/30 23:39
 */
@RestController
@RequestMapping("/user")
@DefaultProperties(defaultFallback = "userGlobalFallback")
@Tag(name = "UserController", description = "用户信息操作相关接口")
public class UserController {

    /**
     * User Service
     */
    @Autowired
    private UserService userService;

    /**
     * Register
     *
     * @param userDto User DTO
     * @return Result page
     */
    @Operation(summary = "用户注册", description = "用户注册：用户通过注册表单输入用户名和密码，执行注册操作",
            security = @SecurityRequirement(name = HttpHeaders.AUTHORIZATION))
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "账号注册成功，直接登录"),
            @ApiResponse(responseCode = "400", description = "用户名已被注册，需要重新注册")
    })
    @MyRateLimit(key = "limit_register", permitsPerSecond = 1, timeout = 500, msg = "系统繁忙，请稍后再尝试！")
    @HystrixCommand(fallbackMethod = "registerUserFallback",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})
    @PreAuthorize("isAnonymous()")
    @PostMapping("/register")
    public ResponseBean register(@Parameter(name = "userDto") @RequestBody UserDto userDto) {
        Map<String, Object> data = new HashMap<>();
        // check whether the username has been used or not
        if (userService.register(userDto)) {
            return new ResponseBean(HttpStatus.OK.value(), "Register successfully and log in", data);
        }
        // if the username has been used, ask the user to re-register
        return new ResponseBean(HttpStatus.BAD_REQUEST.value(), "Username has been used, please try another one", data);
    }

    /**
     * Log-in
     *
     * @param userDto User DTO
     * @return Result page
     */
    @Operation(summary = "用户登录", description = "用户登录：用户通过登录表单输入用户名和密码，执行登录操作",
            security = @SecurityRequirement(name = HttpHeaders.AUTHORIZATION))
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "用户登录成功"),
            @ApiResponse(responseCode = "400", description = "用户名或密码错误，需要重新登录")
    })
    @MyRateLimit(key = "limit_login", permitsPerSecond = 1, timeout = 500, msg = "系统繁忙，请稍后再尝试！")
    @HystrixCommand(fallbackMethod = "loginUserFallback",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})
    @PreAuthorize("isAnonymous()")
    @PostMapping("/login")
    public ResponseBean login(@Parameter(name = "userDto") @RequestBody UserDto userDto) {
        Map<String, String> data = new HashMap<>();
        data = userService.login(userDto);
        if (!data.isEmpty()) {
            return new ResponseBean(HttpStatus.OK.value(), "Log in successfully", data);
        }
        return new ResponseBean(HttpStatus.BAD_REQUEST.value(), "Username or password is incorrect, please retry", data);
    }

    /**
     * Log-out
     *
     * @param userDto User DTO
     * @return Result page
     */
    @Operation(summary = "用户登出", description = "用户登出：用户通过点击登出按钮，执行登出操作",
            security = @SecurityRequirement(name = HttpHeaders.AUTHORIZATION))
    @ApiResponses({
            @ApiResponse(responseCode = "200", description = "用户登出成功"),
            @ApiResponse(responseCode = "400", description = "用户登出失败")
    })
    @HystrixCommand(fallbackMethod = "logoutUserFallback",
            commandProperties = {@HystrixProperty(name = "execution.isolation.thread.timeoutInMilliseconds", value = "1500")})
    @PostMapping("/logout")
    public ResponseBean logout(@Parameter(name = "userDto") @RequestBody UserDto userDto) {
        Map<String, Object> data = new HashMap<>();
        if (userService.logout(userDto)) {
            return new ResponseBean(HttpStatus.OK.value(), "Log out successfully", data);
        }
        return new ResponseBean(HttpStatus.BAD_REQUEST.value(), "Failed to log out", data);
    }

}
